package com.net.xpay.common.service.impl;

import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.stat.UserAccountMoneyLeftStat;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.stat.UserAccountMoneyLeftStatManager;
import com.net.xpay.core.enums.AccountFundType;
import com.net.xpay.core.manager.AccountLogManager;
import com.net.xpay.core.model.AccountLogSearchModel;
import com.net.common.util.LocalDateUtil;
import com.net.xpay.common.service.UserAccountMoneyLeftStatService;
import com.net.shard.ShardUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class UserAccountMoneyLeftStatServiceImpl implements UserAccountMoneyLeftStatService {

    @Autowired
    private UserAccountMoneyLeftStatManager userAccountMoneyLeftStatManager;

    @Autowired
    private UserManager userManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private AccountLogManager accountLogManager;

    @Override
    public void statAllUserAccountMoneyLeft(LocalDate day) {
        // 调用UserManager获取所有的user
        List<User> userList = userManager.listAll();
        // 获取到userList中的id集合
        if (CollectionUtils.isEmpty(userList)) {
            log.warn("statAllUserAccountMoneyLeft There are no users at this time");
            return;
        }
        userList.forEach(user -> {
            if (user.getRegisterTime().toLocalDate().isAfter(day)) {
                //还没注册 无需统计
                return;
            }
            Long userId = user.getId();
            UserAccountMoneyLeftStat stat = new UserAccountMoneyLeftStat();
            // 通过userID获取到userShard
            UserShard userShard = userShardManager.getById(userId);
            try {
                // 先去判断该用户当天转账金额记录是否存在
                stat.setDay(day);
                stat.setUserId(userId);
                boolean exitRecord = hasStated(stat);
                if (exitRecord) {
                    log.warn("doUserTransStat the record of userId={}|day={} is already exist", userId, day);
                    return;
                }
                // 切库处理
                ShardUtil.setShardContext(userShard.getShardId());
                // 获取当天的起始时间和终止时间
                LocalDateTime minEndTime = LocalDateUtil.getDayStart(day);
                LocalDateTime maxEndTime = LocalDateUtil.getDayStart(day.plusDays(1L));
                //查询该用户当天的账户变动值 0点到23点59分59秒
                AccountLogSearchModel searchModel = new AccountLogSearchModel();
                searchModel.setUserId(userId);
                searchModel.setAccountFundType(AccountFundType.MONEY);
                searchModel.setCreateMinTime(minEndTime);
                searchModel.setCreateMaxTime(maxEndTime);
                long change = accountLogManager.sumAccountLog(searchModel);
                UserAccountMoneyLeftStat yesStat = userAccountMoneyLeftStatManager.findByDayAndUserId(day.minusDays(1L), userId);
                if (yesStat == null) {
                   //未初始化过的账号
                    stat.setBeforeMoneyLeft(0L);
                    stat.setChangeMoney(change);
                    stat.setMoneyLeft(change);
                } else {
                    stat.setBeforeMoneyLeft(yesStat.getMoneyLeft());
                    stat.setChangeMoney(change);
                    stat.setMoneyLeft(yesStat.getMoneyLeft() + change);
                }


                // 数据入库
                userAccountMoneyLeftStatManager.save(stat);

            } finally {
                ShardUtil.cleanShardContext();
            }
        });

    }

    private boolean hasStated(UserAccountMoneyLeftStat stat) {
        LocalDate day = stat.getDay();
        Long userId = stat.getUserId();
        // 尝试通过时间加id获取数据
        UserAccountMoneyLeftStat record = userAccountMoneyLeftStatManager.findByDayAndUserId(day, userId);
        // 若果查到了数据，表示不需要在插入记录了
        return record != null;
    }
}
